From ca37264246297117f0cc37052bba67c47c4a8337 Mon Sep 17 00:00:00 2001 From: "kaf24@labyrinth.cl.cam.ac.uk" Date: Fri, 7 Feb 2003 00:41:06 +0000 Subject: [PATCH] bitkeeper revision 1.22.2.4 (3e4300a2YBCCfKhkAv-qMwF-eDVQTQ) Many files: Fast application -> guest-OS trap handling (no longer 'bounce' thru ring 0). --- xen-2.4.16/arch/i386/entry.S | 1 + xen-2.4.16/arch/i386/i8259.c | 10 ++-- xen-2.4.16/arch/i386/io_apic.c | 6 ++- xen-2.4.16/arch/i386/process.c | 10 ++++ xen-2.4.16/arch/i386/traps.c | 53 ++++++++++++++++--- xen-2.4.16/include/asm-i386/irq.h | 20 ++++--- xen-2.4.16/include/asm-i386/processor.h | 9 ++++ .../include/hypervisor-ifs/hypervisor-if.h | 1 + .../arch/xeno/kernel/traps.c | 1 + .../include/asm-xeno/hypervisor.h | 10 ++++ 10 files changed, 96 insertions(+), 25 deletions(-) diff --git a/xen-2.4.16/arch/i386/entry.S b/xen-2.4.16/arch/i386/entry.S index 910e1f19fc..a26c96ccc1 100644 --- a/xen-2.4.16/arch/i386/entry.S +++ b/xen-2.4.16/arch/i386/entry.S @@ -527,6 +527,7 @@ ENTRY(hypervisor_call_table) .long SYMBOL_NAME(do_set_debugreg) .long SYMBOL_NAME(do_get_debugreg) .long SYMBOL_NAME(do_update_descriptor) + .long SYMBOL_NAME(do_set_fast_trap) .rept NR_syscalls-(.-hypervisor_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/xen-2.4.16/arch/i386/i8259.c b/xen-2.4.16/arch/i386/i8259.c index c9d4dfe670..9c6ccc2d93 100644 --- a/xen-2.4.16/arch/i386/i8259.c +++ b/xen-2.4.16/arch/i386/i8259.c @@ -46,7 +46,7 @@ BUILD_COMMON_IRQ() /* * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: - * (these are usually mapped to vectors 0x20-0x2f) + * (these are usually mapped to vectors 0x30-0x3f) */ BUILD_16_IRQS(0x0) @@ -64,7 +64,7 @@ BUILD_COMMON_IRQ() BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3) BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7) BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb) - BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) + BUILD_16_IRQS(0xc) #endif #undef BUILD_16_IRQS @@ -111,7 +111,7 @@ BUILD_COMMON_IRQ() IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3), IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7), IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb), - IRQLIST_16(0xc), IRQLIST_16(0xd) + IRQLIST_16(0xc) #endif }; @@ -344,7 +344,7 @@ void __init init_8259A(int auto_eoi) * outb_p - this has to work on a wide range of PC hardware. */ outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ - outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ + outb_p(0x30 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */ outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ if (auto_eoi) outb_p(0x03, 0x21); /* master does Auto EOI */ @@ -352,7 +352,7 @@ void __init init_8259A(int auto_eoi) outb_p(0x01, 0x21); /* master expects normal EOI */ outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ - outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ + outb_p(0x30 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */ outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode is to be investigated) */ diff --git a/xen-2.4.16/arch/i386/io_apic.c b/xen-2.4.16/arch/i386/io_apic.c index 190e6be36c..c5ae3a3107 100644 --- a/xen-2.4.16/arch/i386/io_apic.c +++ b/xen-2.4.16/arch/i386/io_apic.c @@ -495,8 +495,10 @@ static int __init assign_irq_vector(int irq) return IO_APIC_VECTOR(irq); next: current_vector += 8; - if (current_vector == HYPERVISOR_CALL_VECTOR) - goto next; + /* XXX Skip the guestOS -> Xen syscall vector! XXX */ + if (current_vector == HYPERVISOR_CALL_VECTOR) goto next; + /* XXX Skip the Linux/BSD fast-trap vector! XXX */ + if (current_vector == 0x80) goto next; if (current_vector > FIRST_SYSTEM_VECTOR) { offset++; diff --git a/xen-2.4.16/arch/i386/process.c b/xen-2.4.16/arch/i386/process.c index c8e81de675..6ee5c93c03 100644 --- a/xen-2.4.16/arch/i386/process.c +++ b/xen-2.4.16/arch/i386/process.c @@ -326,6 +326,11 @@ void new_thread(struct task_struct *p, __save_flags(regs->eflags); regs->eflags |= X86_EFLAGS_IF; + + /* No fast trap at start of day. */ + p->thread.fast_trap_idx = 0x20; + p->thread.fast_trap_desc.a = 0; + p->thread.fast_trap_desc.b = 0; } @@ -363,12 +368,17 @@ void new_thread(struct task_struct *p, /* NB. prev_p passed in %eax, next_p passed in %edx */ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { + extern struct desc_struct idt_table[]; struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; struct tss_struct *tss = init_tss + smp_processor_id(); unlazy_fpu(prev_p); + /* Switch the fast-trap handler. */ + CLEAR_FAST_TRAP(&prev_p->thread); + SET_FAST_TRAP(&next_p->thread); + tss->esp0 = next->esp0; tss->esp1 = next->esp1; tss->ss1 = next->ss1; diff --git a/xen-2.4.16/arch/i386/traps.c b/xen-2.4.16/arch/i386/traps.c index 0ce294c9f4..59f293c8f9 100644 --- a/xen-2.4.16/arch/i386/traps.c +++ b/xen-2.4.16/arch/i386/traps.c @@ -277,20 +277,21 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) * Cunning trick to allow arbitrary "INT n" handling. * * We set DPL == 0 on all vectors in the IDT. This prevents any INT - * instruction from trapping to the appropriate vector, when that might not + * instruction from trapping to the appropriate vector, when that might not * be expected by Xen or the guest OS. For example, that entry might be for * a fault handler (unlike traps, faults don't increment EIP), or might * expect an error code on the stack (which a software trap never * provides), or might be a hardware interrupt handler that doesn't like - * being called spuriously. + * being called spuriously. * * Instead, a GPF occurs with the faulting IDT vector in the error code. - * Bit 1 is set to indicate that an IDT entry caused the fault. - * Bit 0 is clear to indicate that it's a software fault, not hardware. + * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is + * clear to indicate that it's a software fault, not hardware. * - * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is okay - * because they can only be triggered by an explicit DPL-checked instruction. - * The DPL specified by the guest OS for these vectors is NOT CHECKED!! + * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is + * okay because they can only be triggered by an explicit DPL-checked + * instruction. The DPL specified by the guest OS for these vectors is NOT + * CHECKED!! */ if ( (error_code & 3) == 2 ) { @@ -298,6 +299,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) ti = current->thread.traps + (error_code>>3); if ( ti->dpl >= (regs->xcs & 3) ) { + if ( (error_code>>3)==0x80 ) { printk("!!!\n"); BUG(); } gtb->flags = GTBF_TRAP_NOCODE; gtb->cs = ti->cs; gtb->eip = ti->address; @@ -570,6 +572,43 @@ long do_set_trap_table(trap_info_t *traps) } +long do_set_fast_trap(int idx) +{ + trap_info_t *ti; + + /* Index 0 is special: it disables fast traps. */ + if ( idx == 0 ) + { + CLEAR_FAST_TRAP(¤t->thread); + memset(idt_table+current->thread.fast_trap_idx, 0, 8); + current->thread.fast_trap_idx = 0x20; + current->thread.fast_trap_desc.a = 0; + current->thread.fast_trap_desc.b = 0; + return 0; + } + + /* + * We only fast-trap vectors 0x20-0x2f, and vector 0x80. + * The former range is used by Windows and MS-DOS. + * Vector 0x80 is used by Linux and the BSD variants. + */ + if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) return -1; + + ti = current->thread.traps + idx; + + CLEAR_FAST_TRAP(¤t->thread); + + current->thread.fast_trap_idx = idx; + current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff); + current->thread.fast_trap_desc.b = + (ti->address & 0xffff0000) | 0x8f00 | (ti->dpl&3)<<13; + + SET_FAST_TRAP(¤t->thread); + + return 0; +} + + long do_fpu_taskswitch(void) { current->flags |= PF_GUEST_STTS; diff --git a/xen-2.4.16/include/asm-i386/irq.h b/xen-2.4.16/include/asm-i386/irq.h index 918f828ce6..936e5bc86c 100644 --- a/xen-2.4.16/include/asm-i386/irq.h +++ b/xen-2.4.16/include/asm-i386/irq.h @@ -10,8 +10,6 @@ #define SA_SHIRQ 0x04000000 #define TIMER_IRQ 0 -/* 256 in architecture, minus 16 allocated to processor. */ -#define NR_IRQS 224 extern void disable_irq(unsigned int); extern void disable_irq_nosync(unsigned int); @@ -21,14 +19,14 @@ extern void enable_irq(unsigned int); * IDT vectors usable for external interrupt sources start * at 0x20: */ -#define FIRST_EXTERNAL_VECTOR 0x20 +#define FIRST_EXTERNAL_VECTOR 0x30 -#define SYSCALL_VECTOR 0x80 /* application -> OS */ -#define KDBENTER_VECTOR 0x81 /* anyone -> KDB */ -#define HYPERVISOR_CALL_VECTOR 0x82 /* OS -> monitor*/ +#define NR_IRQS (256 - FIRST_EXTERNAL_VECTOR) + +#define HYPERVISOR_CALL_VECTOR 0x82 /* - * Vectors 0x20-0x2f are used for ISA interrupts. + * Vectors 0x30-0x3f are used for ISA interrupts. */ /* @@ -55,11 +53,11 @@ extern void enable_irq(unsigned int); #define LOCAL_TIMER_VECTOR 0xef /* - * First APIC vector available to drivers: (vectors 0x30-0xee) - * we start at 0x31 to spread out vectors evenly between priority - * levels. (0x80 is the syscall vector) + * First APIC vector available to drivers: (vectors 0x40-0xee) + * we start at 0x41 to spread out vectors evenly between priority + * levels. (0x82 is the syscall vector) */ -#define FIRST_DEVICE_VECTOR 0x31 +#define FIRST_DEVICE_VECTOR 0x41 #define FIRST_SYSTEM_VECTOR 0xef extern int irq_vector[NR_IRQS]; diff --git a/xen-2.4.16/include/asm-i386/processor.h b/xen-2.4.16/include/asm-i386/processor.h index b3f496c5bc..02868d5b23 100644 --- a/xen-2.4.16/include/asm-i386/processor.h +++ b/xen-2.4.16/include/asm-i386/processor.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -352,15 +353,23 @@ struct thread_struct { /* floating point info */ union i387_union i387; /* Trap info. */ + int fast_trap_idx; + struct desc_struct fast_trap_desc; trap_info_t traps[256]; }; +#define CLEAR_FAST_TRAP(_p) \ + (memset(idt_table + (_p)->fast_trap_idx, 0, 8)) +#define SET_FAST_TRAP(_p) \ + (memcpy(idt_table + (_p)->fast_trap_idx, &((_p)->fast_trap_desc), 8)) + #define INIT_THREAD { \ sizeof(idle0_stack) + (long) &idle0_stack, /* esp0 */ \ 0, 0, 0, 0, 0, 0, \ { [0 ... 7] = 0 }, /* debugging registers */ \ 0, 0, 0, \ { { 0, }, }, /* 387 state */ \ + 0, { 0, 0 }, \ { {0} } /* io permissions */ \ } diff --git a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h index 9c9d752efd..a0cfc7ae59 100644 --- a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h +++ b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h @@ -88,6 +88,7 @@ typedef struct #define __HYPERVISOR_set_debugreg 11 #define __HYPERVISOR_get_debugreg 12 #define __HYPERVISOR_update_descriptor 13 +#define __HYPERVISOR_set_fast_trap 14 #define TRAP_INSTR "int $0x82" diff --git a/xenolinux-2.4.16-sparse/arch/xeno/kernel/traps.c b/xenolinux-2.4.16-sparse/arch/xeno/kernel/traps.c index 2a546b49d5..c274928ae9 100644 --- a/xenolinux-2.4.16-sparse/arch/xeno/kernel/traps.c +++ b/xenolinux-2.4.16-sparse/arch/xeno/kernel/traps.c @@ -562,5 +562,6 @@ static trap_info_t trap_table[] = { void __init trap_init(void) { HYPERVISOR_set_trap_table(trap_table); + HYPERVISOR_set_fast_trap(SYSCALL_VECTOR); cpu_init(); } diff --git a/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h index e6b2c13024..d25c6f8171 100644 --- a/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h +++ b/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h @@ -288,6 +288,16 @@ static inline int HYPERVISOR_update_descriptor( : "=a" (ret) : "0" (__HYPERVISOR_set_gdt), "b" (pa), "c" (word1), "d" (word2) ); + return ret; +} + +static inline int HYPERVISOR_set_fast_trap(int idx) +{ + int ret; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) : "0" (__HYPERVISOR_set_fast_trap), + "b" (idx) ); return ret; } -- 2.30.2